package org.hackystat.linkedservicedata.ui.network;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import org.hackystat.linkedservicedata.client.LinkedServiceDataClientException;
import org.hackystat.linkedservicedata.ui.LinkedServiceDataUI;

/**
 * Panel to handle the list of external LiSeD servers included in the Hackystat network.
 *
 * @author Myriam Leggieri.
 *
 */
public class NetworkPanel extends JPanel implements ActionListener {
  /**
   *
   */
  private static final long serialVersionUID = -4751258269555112338L;

  private LinkedServiceDataUI mainframe = null;

  /** Add server button. */
  private JButton addServerButton = null;
  /** Remove server button. */
  private JButton removeServerButton = null;
  /** Refresh button. */
  private JButton refreshButton = null;
  /** List of servers. */
  private JList serversList = null;
  /** List of servers label. */
  private JLabel serversListLabel = null;
  /** Server URI label. */
  private JLabel serversURILabel = null;
  /** Server URI text. */
  private JTextField serversURIText = null;
  /** Server admin label. */
  private JLabel serversAdminLabel = null;
  /** Server admin text. */
  private JTextField serversAdminText = null;
  /** Server password label. */
  private JLabel serversPasswordLabel = null;
  /** Server Password text. */
  private JPasswordField serversPasswordText = null;
  /** List of servers'data. */
  private HashMap<String, String[]> profilesList = null;

  public NetworkPanel(LinkedServiceDataUI mainframe) {
    this.mainframe = mainframe;
    resetPanel();
  }

  /**
   * Monitor a correct displaying of this tab panel while the user is browsing between tabs. If he
   * is logged then the list of profiles for this panel is already updated and then it's not refresh
   * now.
   */
  public void prepareDisplaying() {
    if (!mainframe.isLogged()) {
      profilesList = new HashMap<String, String[]>();
    }
    else if (profilesList.isEmpty()) {
      refreshProfiles();
    }
    refresh();
  }

  /**
   * Forces the resetting of the whole panel and re-fills it only if the current user is logged.
   * This is used after changes to the authentication state.
   */
  public void resetPanel() {
    this.profilesList = new HashMap<String, String[]>();
    if (mainframe.isLogged()) {
      refreshProfiles();
    }
    refresh();
  }

  public void refreshProfiles() {
    try {
      this.profilesList = mainframe.getLiSeDClient().getAssociatedLiSeDServers();
    }
    catch (LinkedServiceDataClientException e1) {
      JOptionPane.showMessageDialog(this, e1.getMessage(), "Hackystat - Error Message",
          JOptionPane.ERROR_MESSAGE);
      e1.printStackTrace();
    }
  }

  public void refresh() {
    this.removeAll();
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setBackground(Color.WHITE);
    if (mainframe.isLogged()) {
      initJLists();
      initLabels();
      initJTextFields();

      panel.add(getActions());
      panel.setBorder(BorderFactory.createLineBorder(Color.blue));
    }
    panel.setBackground(Color.white);
    JScrollPane listScrollPane = new JScrollPane(panel);
    listScrollPane = mainframe.initSubPanelScrollPane(listScrollPane);
    this.add(listScrollPane);
    this.validate();
  }

  private Component getActions() {
    if (addServerButton == null) {
      addServerButton = new JButton("Add >>");
      addServerButton = mainframe.initButton(addServerButton, this, mainframe.buttonDimension,
          "Add the specified server URI " + "to the list");
    }
    if (removeServerButton == null) {
      removeServerButton = new JButton("Remove <<");
      removeServerButton = mainframe.initButton(removeServerButton, this,
          mainframe.buttonDimension, "Remove the specified server URI " + "from the list");
    }
    if (refreshButton == null) {
      refreshButton = new JButton("Refresh");
      refreshButton = mainframe.initButton(refreshButton, this, mainframe.buttonDimension,
          "Refresh data.");
    }
    JPanel horiz = new JPanel();
    horiz.setLayout(new BoxLayout(horiz, BoxLayout.X_AXIS));
    horiz.setBackground(Color.white);

    JPanel vertic = new JPanel();
    vertic.setLayout(new BoxLayout(vertic, BoxLayout.Y_AXIS));
    vertic.setBackground(Color.white);
    vertic.add(serversURILabel);
    vertic.add(Box.createVerticalStrut(1));
    vertic.add(serversURIText);
    vertic.add(Box.createVerticalStrut(3));
    vertic.add(serversAdminLabel);
    vertic.add(Box.createVerticalStrut(1));
    vertic.add(serversAdminText);
    vertic.add(Box.createVerticalStrut(3));
    vertic.add(serversPasswordLabel);
    vertic.add(Box.createVerticalStrut(1));
    vertic.add(serversPasswordText);
    vertic.add(Box.createVerticalStrut(5));
    vertic.add(addServerButton);
    vertic.add(Box.createVerticalStrut(1));
    vertic.add(removeServerButton);
    vertic.add(Box.createVerticalStrut(20));
    vertic.add(refreshButton);
    horiz.add(vertic);
    horiz.add(Box.createHorizontalStrut(3));
    vertic = new JPanel();
    vertic.setLayout(new BoxLayout(vertic, BoxLayout.Y_AXIS));
    vertic.setBackground(Color.white);
    vertic.add(serversListLabel);
    vertic.add(Box.createVerticalStrut(1));
    JScrollPane scroll = new JScrollPane(serversList);
    scroll.setPreferredSize(new Dimension(600, 800));
    scroll.setMaximumSize(new Dimension(600, 800));
    scroll.setMinimumSize(new Dimension(600, 800));
    vertic.add(scroll);
    horiz.add(vertic);
    return horiz;
  }

  private void initJTextFields() {
    serversAdminText = new JTextField(10);
    serversAdminText = mainframe.initTextField(serversAdminText, null, true);

    serversURIText = new JTextField(10);
    serversURIText = mainframe.initTextField(serversURIText, null, true);

    serversPasswordText = new JPasswordField(10);
    serversPasswordText = mainframe.initPasswordField(serversPasswordText, null, true);
  }

  private void initLabels() {
    serversAdminLabel = new JLabel();
    serversAdminLabel = mainframe.initLabel(serversAdminLabel, "Administer's E-mail:");

    serversListLabel = new JLabel();
    serversListLabel = mainframe.initLabel(serversListLabel,
        "List of servers included in your Hackystat network:");

    serversPasswordLabel = new JLabel();
    serversPasswordLabel = mainframe.initLabel(serversPasswordLabel, "Administer's Password:");

    serversURILabel = new JLabel();
    serversURILabel = mainframe.initLabel(serversURILabel, "Server URI:");
  }

  private void initJLists() {
    DefaultListModel model = new DefaultListModel();
    for (String uri : profilesList.keySet()) {
      model.addElement(uri + " - admin:" + profilesList.get(uri)[0]);
    }
    serversList = new JList(model);
    serversList = mainframe.initJList(serversList);

  }

  @Override
  public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    if (source.equals(addServerButton)) {
      String uri = serversURIText.getText(), admin = serversAdminText.getText(), password = "", empty = "";
      char[] pass = serversPasswordText.getPassword();
      for (int i = 0; i < pass.length; i++) {
        password += pass[i];
      }
      if (uri != null && !uri.trim().equals(empty) && admin != null && !admin.trim().equals(empty)
          && password != null && !password.equals(empty)) {
        HashMap<String, String[]> tmp = new HashMap<String, String[]>();
        tmp.put(uri, new String[] { admin, password });
        try {
          mainframe.getLiSeDClient().addNetworkLiSeDServer(tmp);
        }
        catch (LinkedServiceDataClientException e1) {
          JOptionPane.showMessageDialog(this, e1.getMessage(), "Hackystat - Error Message",
              JOptionPane.ERROR_MESSAGE);
          e1.printStackTrace();
          return;
        }
        profilesList.put(uri, new String[] { admin, password });
        DefaultListModel model = (DefaultListModel) serversList.getModel();
        model.addElement(uri + " - " + admin);
        serversList.repaint();
      }
      else {
        JOptionPane.showMessageDialog(this, "Server URI, Administer's email or password missing.",
            "Hackystat - Warning Message", JOptionPane.WARNING_MESSAGE);
        return;
      }
    }
    else if (source.equals(removeServerButton)) {
      int index = serversList.getSelectedIndex();
      if (index != -1) {
        DefaultListModel model = (DefaultListModel) serversList.getModel();
        String[] split = String.valueOf(model.getElementAt(index)).split(" - ");
        if (split.length == 2) {
          try {
            mainframe.getLiSeDClient().removeAssociatedLiSeDServers(split[0].trim());
          }
          catch (LinkedServiceDataClientException e1) {
            JOptionPane.showMessageDialog(this, e1.getMessage(), "Hackystat - Error Message",
                JOptionPane.ERROR_MESSAGE);
            e1.printStackTrace();
            return;
          }

          model.remove(index);
          profilesList.remove(split[0].trim());
          serversList.repaint();
        }
      }
    }
    else if (source.equals(refreshButton)) {
      refreshProfiles();
      refresh();
    }
  }

}
